<?php

namespace api\admin;


use utils\phpMQTT;

//mqtt类
class mq
{
    //测试
    public function test()
    {
        $res = $this->printOrder(72);
        return out_right($res);
    }

    //打印结账单
    public function printOrder(int $order_id)
    {
        $con = con();
        $order = mysqli_query($con, "select * from `order` where id=$order_id and status=1");
        $order = mysqli_fetch_all($order, true);
        if (count($order) === 0) {
            mysqli_close($con);
            return '订单非法！';
        }
        $data = $order[0];
        $item = mysqli_query($con, "SELECT a.*,b.name as goods_name FROM `order_item` a left join goods b on (a.goods_id=b.id) where a.order_id=$order_id");
        $item = mysqli_fetch_all($item, true);

        $order_no = $data['order_no'];
        $create_time = date('Y-m-d H:i:s', $data['create_time']);

        $money = sprintf("%.2f", $data['money'] / 100);
        $name = $data['name'];//支付人
        $phone = $data['phone'];
        $address = $data['address'];
        $type = (int)$data['type'];
        $send_content = '';
        $num=(int)$data['num'];
        switch ((int)$data['time_type']) {
            case 0://未定义
                $time_type_name = '';
                break;
            case 1://早餐
                $time_type_name = '早餐';
                break;
            case 2://午餐
                $time_type_name = '午餐';
                break;
            case 3://晚餐
                $time_type_name = '晚餐';
                break;
        }
        switch ((int)$data['pay_type']) {
            case 0://余额支付
                $pay_type_name = '余额支付';
                break;
            case 1://微信支付
                $pay_type_name = '微信支付';
                break;
        }
        switch ($type) {
            case 0://堂食
                $type_name = '堂食';
                break;
            case 1://配送
                $send_content .=
                    "联系人：$name \r\n" .
                    "联系电话：$phone \r\n" .
                    "配送地址：$address \r\n";
                $type_name = '配送';
                break;
            case 2://预订
                $pre_time = date('Y-m-d', $data['create_time']) . ' ' . $data['pre_time'];
                $send_content .=
                    "预订送达时间： $pre_time\r\n" .
                    "联系人：$name \r\n" .
                    "联系电话：$phone \r\n" .
                    "配送地址：$address \r\n";
                $type_name = '预订';
                break;
        }

        $item_content = '';
        for ($i = 0; $i < count($item); $i++) {
            $goods_name = $item[$i]['goods_name'];
            $num = $item[$i]['num'];
            $specs_info = $item[$i]['specs_info'];
            $item_content .= "$goods_name        x$num    $specs_info	\r\n";
        }
        if ($item_content === '') {
            $item_header = '';
        } else {
            $item_header = "商品名称        数量    规格	\r\n";
        }
        $now_time = date('Y-m-d H:i:s');

        // 定义字体调整命令
        $double_size = "\x1D\x21\x01"; // 宽高都放大2倍
        $normal_size = "\x1D\x21\x00"; // 恢复正常大小
        $font_weight="\x1B\x45\x11";//加粗

        $content =
            $double_size.$font_weight."*            结账单           *\r\n" .
            "*            机关食堂          *\r\n" .
            $normal_size."================================\r\n" .
            "打印时间：$now_time\r\n" .
            "支付时间：$create_time\r\n" .
            "支付人：$name\r\n" .
            "订单号：$order_no	\r\n" .
            "餐类型：$time_type_name	\r\n" .
            "订单类型：$type_name	\r\n" .
            "--------------------------------	\r\n" .
            $item_header .
            $item_content .
            "--------------------------------	\r\n" .
            $double_size."份数: ".$num."份\r\n" .
            $normal_size."支付类型: $pay_type_name	\r\n" .
            "订单金额:￥ $money 元	\r\n" .
            "================================	\r\n" .
            $send_content .
            "================================	\r\n" .
            "  推行健康饮食   打造绿色食堂     \r\n" .
            "          谢谢惠顾	\r\n" .
            "         欢迎下次光临	\r\n" .
            "	\r\n" .
            "	\r\n" .
            "	\r\n" .
            "	\r\n" .
            "	\r\n" .
            "	\r\n";
        $print_id = mysqli_query($con, "select * from setting where id=8");
        $print_id = mysqli_fetch_all($print_id, true);
        if (count($print_id) === 0) {
            mysqli_close($con);
            return '缺少打印机设置！请联系技术！';
        }
        $print_id = $print_id[0]['value_1'];
        $res = $this->print($content, $print_id);
        if(empty($res)){
            $res='打印成功';
        }else{
            $res = json_encode($res);
        }
        $time = time();
        $res = mysqli_query($con, "insert into print_log(res,print_id,content,create_time) values('$res','$print_id','$content',$time)");
        mysqli_close($con);
        if ($res) {
            return '';
        } else {
            return '打印日志插入失败！';
        }
    }

    //推送消息到打印机
    public function print($content, $topic)
    {

        $server = $GLOBALS['print_server'];     // change if necessary
        $port = $GLOBALS['print_port'];                     // change if necessary
        $username = $GLOBALS['print_user'];                   // set your username
        $password = $GLOBALS['print_password'];                   // set your password
        $client_id = '100'; // make sure this is unique for connecting to sever - you could use uniqid()

        $mqtt = new phpMQTT($server, $port, $client_id);
        $status = $mqtt->connect(true, NULL, $username, $password);

        $ZPL = bin2hex($content);
        $hexBin = pack("H*", $ZPL);
        $len = strlen($hexBin) + 4;//打印指定尾部4字节
        $len_MSB = dechex(($len & 0xff00) >> 8);
        $len_LSB = dechex($len & 0x00ff);
        $lenMSBStr = str_pad($len_MSB, 2, 0, STR_PAD_LEFT);
        $lenLSBSTR = str_pad($len_LSB, 2, 0, STR_PAD_LEFT);
        $check = $this->crc16($content);
        $content = pack("H*", "1E1001" . $lenMSBStr . $lenLSBSTR . $ZPL . "1B63" . $check);
        if ($status) {
            $res = $mqtt->publish($topic, $content, 2, false);
            $mqtt->close();
            if (empty($res)) {
                return '';
            } else {
                return $res;
            }
            return '';
        } else {
            return '失败！';
        }
    }

    public function reverseChar($char)
    {
        $byte = ord($char);
        $tmp = 0;
        for ($i = 0; $i < 8; ++$i) {
            if ($byte & (1 << $i)) {
                $tmp |= (1 << (7 - $i));
            }
        }
        return chr($tmp);
    }

    /**
     * 将一个字节流按比特位反转 eg: 'AB'(01000001 01000010)  --> '\x42\x82'(01000010 10000010)
     * @param $str
     */
    public function reverseString($str)
    {
        $m = 0;
        $n = strlen($str) - 1;
        while ($m <= $n) {
            if ($m == $n) {
                $str[$m] = $this->reverseChar($str[$m]);
                break;
            }
            $ord1 = $this->reverseChar($str[$m]);
            $ord2 = $this->reverseChar($str[$n]);
            $str[$m] = $ord2;
            $str[$n] = $ord1;
            $m++;
            $n--;
        }
        return $str;
    }

    /**
     * @param string $str 待校验字符串
     * @param int $polynomial 二项式
     * @param int $initValue 初始值
     * @param int $xOrValue 输出结果前异或的值
     * @param bool $inputReverse 输入字符串是否每个字节按比特位反转
     * @param bool $outputReverse 输出是否整体按比特位反转
     * @return int
     */
    public function crc16($str, $polynomial = 0x1021, $initValue = 0xffff, $xOrValue = 0xffff, $inputReverse = true, $outputReverse = true)
    {
        $crc = $initValue;

        for ($i = 0; $i < strlen($str); $i++) {
            if ($inputReverse) {
                // 输入数据每个字节按比特位逆转
                $c = ord($this->reverseChar($str[$i]));
            } else {
                $c = ord($str[$i]);
            }
            $crc ^= ($c << 8);
            for ($j = 0; $j < 8; ++$j) {
                if ($crc & 0x8000) {
                    $crc = (($crc << 1) & 0xffff) ^ $polynomial;
                } else {
                    $crc = ($crc << 1) & 0xffff;
                }
            }
        }
        if ($outputReverse) {
            // 把低地址存低位，即采用小端法将整数转换为字符串
            $ret = pack('cc', $crc & 0xff, ($crc >> 8) & 0xff);
            // 输出结果按比特位逆转整个字符串
            $ret = $this->reverseString($ret);
            // 再把结果按小端法重新转换成整数
            $arr = unpack('vshort', $ret);
            $crc = $arr['short'];
        }
        return dechex($crc ^ $xOrValue);
    }

}



